home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Files / Folder Watching / Folder Watcher FBA ƒ / Sources / FBA.c next >
Encoding:
C/C++ Source or Header  |  1997-03-10  |  6.3 KB  |  276 lines  |  [TEXT/CWIE]

  1. // FBA.c
  2. //
  3. // Folder Watcher FBA by Greg Sutton
  4. // Base code for this FBA by Chris White
  5. // ©Apple Computer Inc 1996, all rights reserved.
  6.  
  7.  
  8.     // Includes
  9. #include "FBA.h"
  10. #include "FBAAppleEvents.h"
  11. #include "FBATask.h"
  12. #include "FBALists.h"
  13.  
  14. #include <Gestalt.h>
  15. #include <LowMem.h>
  16. #include <Events.h>
  17. #include <Notification.h>
  18. #include <Resources.h>
  19.  
  20. #ifdef DEVELOPMENT
  21.     #include <TextEdit.h>
  22.     #include <Dialogs.h>
  23. #endif
  24.  
  25.  
  26.     // Prototypes
  27. static void             IncreaseFBAStack(Size extraBytes);
  28. static Boolean            HasFullExtFSDispatching( void );
  29. static Boolean            HasProcessManager( void );
  30. static void                InitCycleTime( void );
  31. static unsigned long    GetResourceCycleTime( void );
  32.  
  33. static void                CheckEventQueue( void );
  34.  
  35. static void                Notify( StringPtr notice, Boolean fFatal );
  36.  
  37. static pascal void        MyResponse( NMRecPtr n );
  38.  
  39.  
  40.     // Globals
  41. #if !defined(THINK_C) && !defined(__MWERKS__)
  42.         QDGlobals       qd;
  43. #endif
  44.  
  45. short             gQuit = false;
  46. unsigned long    gCycleTime;            // Time requested to check all folders
  47.  
  48.     // Constants
  49. const unsigned long    DefaultCycleTime = 30;    // Default cycle time for all folders
  50.                                             // to be checked in seconds.
  51. const short            StackSize = 32;            // Default stack size for an FBA is 2K
  52.                                             // Set StackSize to the K wanted.
  53.  
  54.  
  55. void    main( void )
  56. {
  57.     Boolean            fQuit;
  58.     
  59.     IncreaseFBAStack(StackSize * 1024);
  60.  
  61.     MaxApplZone();
  62.     
  63.     InitGraf( &qd.thePort );    // Always call InitGraf; otherwise,
  64.                                 // AppleEvents, Random(), and other calls won't work.
  65.  
  66. #ifdef DEVELOPMENT    // See 'FBA.h' for #define
  67.     InitFonts( );
  68.     InitWindows( );
  69.     InitMenus( );
  70.     TEInit( );
  71.     InitDialogs( 0L );
  72.     InitCursor( );
  73. #endif
  74.  
  75.     if ( noErr != InitAppleEvents( ) )
  76.         Notify( "\pFolder Watcher failed to initialize Apple events", kFatalErr );
  77.     
  78.     if ( ! HasFullExtFSDispatching( ) )
  79.         Notify( "\pFolder Watcher failed due to limited CatSearch", kFatalErr );
  80.     
  81.     if ( ! HasProcessManager( ) )
  82.         Notify( "\pFolder Watcher failed due to no Process Manager", kFatalErr );
  83.         
  84.     if ( ! InitTask( ) )
  85.         Notify( "\pFolder Watcher failed due to bad task initialization", kFatalErr );
  86.  
  87.     InitWatchFolders( );
  88.     InitCycleTime( );
  89.     
  90.     fQuit = gQuit;                        // Initialization may set gQuit to true
  91.     
  92.     while ( ! fQuit )
  93.     {
  94.         CheckEventQueue( );
  95.         
  96.         if ( gQuit )                    // We want to quit
  97.             fQuit = CanQuitTask( );        // Check that our task can quit now
  98.     }
  99. }
  100.  
  101. // Increase the space allocated for the background only application
  102. // stack.
  103. // 
  104. // Call this routine before calling MaxApplZone, during program
  105. // initialization.
  106. // 
  107. // Warning: 
  108. //     SetApplLimit always sets the stack to at least as large as the
  109. //     default stack for the machine (8K on machines with original
  110. //     QuickDraw, 24K on machines with Color QuickDraw), so the
  111. //     application partition must be large enough to accommodate an
  112. //     appropriate stack and heap.
  113. // 
  114. // Call this only once, at the beginning of the background only
  115. // application.
  116. // 
  117. // Another warning: 
  118. //     Don't bother trying to set the stack size to something lower
  119. //     than 24K. If SetApplLimit is called to do this, it will
  120. //     silently lower ApplLimit to a 24K stack.
  121.  
  122. static void IncreaseFBAStack(Size extraBytes)
  123. {
  124.     THz        myZone;
  125.     SysEnvRec    sys;
  126.  
  127.     SysEnvirons(1, &sys);
  128.  
  129.     if (sys.systemVersion < 0x0755)
  130.     {
  131.         // Check that we aren't running with a corrupt heap. If we are,
  132.         // fix the problem.  This was a bug with FBA's before System 7.5.5.  
  133.         myZone = GetZone();
  134.         if (myZone->bkLim != LMGetHeapEnd())
  135.             LMSetHeapEnd(myZone->bkLim);
  136.     }
  137.     // Increase the stack size by lowering the heap limit.
  138.     SetApplLimit((Ptr) ((Size) GetApplLimit() - extraBytes));
  139. }
  140.  
  141.  
  142. static void    CheckEventQueue( void )
  143. {
  144.     long                    sleepTicks = 1;    // First time through return from
  145.                                             //  WaitNextEvent() as quick as possible.
  146.     EventRecord             anEvent;
  147.     OSErr                    err;
  148.  
  149.     WaitNextEvent( highLevelEventMask, &anEvent, sleepTicks, NULL );
  150.     
  151.     switch ( anEvent.what )
  152.     {
  153.         case kHighLevelEvent :
  154.             err = DoAppleEvent( &anEvent );
  155.         break;
  156.     }
  157.     
  158.         // Call background task no matter if event
  159.         //  is a high level or null event.
  160.     sleepTicks = DoBackgroundTask( );        // Do our background task or return
  161.                                             //  an updated sleep time.
  162. }
  163.  
  164.  
  165. // See if File Manager will pass CatSearch requests to external file systems.
  166.  
  167. static Boolean    HasFullExtFSDispatching( void )
  168. {
  169.     long        response;
  170.     Boolean        result = false;
  171.  
  172.     if ( noErr == Gestalt( gestaltFSAttr, &response ) )
  173.         result = ((response & (1L << gestaltFullExtFSDispatching)) != 0);
  174.         
  175.     return result;
  176. }
  177.  
  178.  
  179. // Check that we have the process manager
  180.  
  181. static Boolean    HasProcessManager( void )
  182. {
  183.     long        response;
  184.     Boolean        result = false;
  185.  
  186.     if ( noErr == Gestalt( gestaltOSAttr, &response ) )
  187.         result = true;
  188.         
  189.     return result;
  190. }
  191.  
  192.  
  193. static void    InitCycleTime( void )
  194. {
  195.     gCycleTime = GetResourceCycleTime();
  196. }
  197.  
  198.  
  199. unsigned long    GetCycleTime( void )
  200. {
  201.     return gCycleTime;
  202. }
  203.  
  204.  
  205. // If there are 'Cycl' resources then use the first of these for the sleep time.
  206. // Otherwise use the default cycle time. The time is supposed to be in seconds.
  207.  
  208. static unsigned long GetResourceCycleTime( void )
  209. {
  210.     short            count;
  211.     Handle             aHandle;
  212.     unsigned long    result = DefaultCycleTime;
  213.     
  214.     count = Count1Resources( kCycleTimeResource );
  215.     if ( count )
  216.     {
  217.         aHandle = Get1IndResource( kCycleTimeResource, 1 );
  218.         if ( aHandle )
  219.         {
  220.             result = *(unsigned long *) *aHandle;
  221.             ReleaseResource( aHandle );
  222.         }
  223.     }
  224.     
  225.     return result;
  226. }
  227.  
  228.  
  229.  
  230. static pascal void MyResponse ( NMRecPtr n )
  231. {
  232.     DisposePtr ( (Ptr) n->nmStr );
  233.     NMRemove ( n );
  234.     if ( ! n->nmRefCon )        // true if error was fatal
  235.         DisposePtr ( (Ptr) n );
  236.     else
  237.         n->nmRefCon = 0L;
  238.     
  239.     return;
  240. }
  241.  
  242.  
  243. // Use the Notification manager to display a message.
  244. // Pass true to fFatal if the applcation is to quit afterwards.
  245.  
  246. void    Notify( StringPtr notice, Boolean fFatal )
  247. {
  248.     // remember, no user interface to play with
  249.     NMRecPtr    notePtr;
  250.     OSErr        err;
  251.     
  252.     notePtr = (NMRecPtr) NewPtr ( sizeof ( NMRec ) );
  253.     if ( MemError ( ) )
  254.         return;
  255.     
  256.     notePtr->qType = nmType;            // standard queue type for NM
  257.     notePtr->nmMark = 0;                // background only
  258.     notePtr->nmIcon = 0L;
  259.     notePtr->nmSound = (Handle) -1L;    // use system alert snd
  260.     notePtr->nmStr = NULL;
  261.     notePtr->nmStr = (StringPtr) NewPtr ( sizeof ( Str255 ) );
  262.     BlockMoveData( notice, notePtr->nmStr, notice[0] + 1 );
  263.     notePtr->nmResp = NewNMProc( MyResponse );
  264.     notePtr->nmRefCon = fFatal;
  265.     
  266.     err = NMInstall ( notePtr );
  267.     if ( err == noErr && fFatal )
  268.     {
  269.         while ( notePtr->nmRefCon )
  270.             CheckEventQueue( );
  271.         gQuit = true;
  272.     }
  273.  
  274.     return;
  275. }
  276.